﻿import pygame
from pygame.locals import *
import random
from RotateHose import *
from Point3D import *
from SimpleButton import *
import math
from pygame.cursors import ball

class GamePartOne:
	def __init__(self, game_app, py_screen):
		print "game part 1 create"
		self.screen = py_screen
		self.ws = game_app
		self.windows_bgcolor = (0,51,102)		
		self.mouse_pos = (0,0)
		self.bals = []
		self.numBalls = 25
		self.fl = 250
		self.vpX = 150.0
		self.vpY = 224.0
		self.top = -100
		self.bottom = 100
		self.left = -100
		self.right = 100
		self.front = 100
		self.back = -100
		
		self.dna_colors = ((255,0,0),(0,255,0),(0,0,255),(255,255,0),(255,0,255),(0,255,255))
		
		self.atom_images_norm = []
		self.atom_images_norm.append(pygame.image.load('data/graphics/atoms/atom_1.png').convert_alpha())
		self.atom_images_norm.append(pygame.image.load('data/graphics/atoms/atom_2.png').convert_alpha())
		self.atom_images_norm.append(pygame.image.load('data/graphics/atoms/atom_3.png').convert_alpha())
		self.atom_images_norm.append(pygame.image.load('data/graphics/atoms/atom_4.png').convert_alpha())
		
		self.atom_images_over = []
		self.atom_images_over.append(pygame.image.load('data/graphics/atoms/atom_1_over.png').convert_alpha())
		self.atom_images_over.append(pygame.image.load('data/graphics/atoms/atom_2_over.png').convert_alpha())
		self.atom_images_over.append(pygame.image.load('data/graphics/atoms/atom_3_over.png').convert_alpha())
		self.atom_images_over.append(pygame.image.load('data/graphics/atoms/atom_4_over.png').convert_alpha())
		
		self.rot_speed = math.pi / 120
		self.cur_color = (128,63,63)
		self.line_color = (0,0,0)
		self.line_width = 5
		self.ran_bal = 20
		#################################
		self.is_mouse_down = False
		dnaDown = 11.2
		startX = 0
		startY = -((self.numBalls / 2) * dnaDown)
		startZ = 0
		rotRad = math.pi / 10
		self.dnaRad = 75
		self.one = 1
		self.zero = 0
		self.coss = math.cos(self.rot_speed)
		self.sinn = math.sin(self.rot_speed)
		
		self.num_text = []
		
		self.dna_1 = []
		self.dna_2 = []
		
		for i in range(0,self.numBalls):
		
			self.num_text.append(self.ws.test_font.render("%s" % i,False,(255,255,255)))
			
			new_ball = Point3D()
			new_ball.num = i
			new_ball.xpos = startX + (math.cos(rotRad * i) * self.dnaRad)
			new_ball.ypos = startY + (dnaDown * i);
			new_ball.zpos = startZ + (math.sin(rotRad * i) * self.dnaRad)
			new_ball.color = self.dna_colors[random.randint(0,5)]
			new_ball.atom_num = random.randint(0,3)
			new_ball.image_norm = self.atom_images_norm[new_ball.atom_num]
			self.RasterBall(new_ball)

			self.dna_1.append(new_ball)
			
			new_ball.dna = self.dna_1

			
			"""if len(self.bals) > 0:
				new_ball.next = self.bals[-1]"""
			self.bals.append(new_ball)
			
			sec_bal = Point3D()
			sec_bal.num = i
			sec_bal.xpos = startX + (math.cos(rotRad * i + math.pi) * self.dnaRad)
			sec_bal.ypos = startY + (dnaDown * i);
			sec_bal.zpos = startZ + (math.sin(rotRad * i + math.pi) * self.dnaRad)
			sec_bal.color = self.dna_colors[random.randint(0,5)]
			sec_bal.atom_num = random.randint(0,3)
			sec_bal.image_norm = self.atom_images_norm[sec_bal.atom_num]
			self.RasterBall(sec_bal)
			
			self.bals.append(sec_bal)
			
			self.dna_2.append(sec_bal)
			sec_bal.dna = self.dna_2
			
			
			
		self.bals = sorted(self.bals, key=lambda student: student.zpos, reverse=True)
		
		self.rect_left_btn = pygame.Rect(400,400,100,60)
		self.rect_right_btn = pygame.Rect(500,400,100,60)
		self.RotationFunc = None
		self.last_select_ball = None
		
		self.rot_sin_angle_right = math.sin(math.pi / 100)
		self.rot_sin_angle_left = -(math.sin(math.pi / 100))
		self.rot_cos_angle_right = math.cos(math.pi / 100)
		self.rot_cos_angle_left = -(math.cos(math.pi / 100))
		
		self.rem_img = pygame.image.load("data/graphics/first_dna_part.png").convert()
		
		self.bg_image = pygame.image.load("data/graphics/bgs/bg_1.png").convert()
		
		#левая стрелка
		self.left_arrow_images = []
		self.left_arrow_images.append(pygame.image.load("data/graphics/arrows/larrow_up.png").convert_alpha())
		self.left_arrow_images.append(pygame.image.load("data/graphics/arrows/larrow_over.png").convert_alpha())
		self.left_arrow_images.append(pygame.image.load("data/graphics/arrows/larrow_down.png").convert_alpha())
		
		self.left_arrow = SimpleButton(self.rect_left_btn,self.left_arrow_images, self.screen)
		
		
		#правая стрелка
		
		self.right_arrow_images = []
		self.right_arrow_images.append(pygame.image.load("data/graphics/arrows/rarrow_up.png").convert_alpha())
		self.right_arrow_images.append(pygame.image.load("data/graphics/arrows/rarrow_over.png").convert_alpha())
		self.right_arrow_images.append(pygame.image.load("data/graphics/arrows/rarrow_down.png").convert_alpha())
		
		self.right_arrow = SimpleButton(self.rect_right_btn,self.right_arrow_images, self.screen)
		
		#кнопка закрыть уровень
		
		self.close_btn_images = []
		self.close_btn_images.append(pygame.image.load("data/graphics/buttons/close_btn_up.png").convert_alpha())
		self.close_btn_images.append(pygame.image.load("data/graphics/buttons/close_btn_over.png").convert_alpha())
		self.close_btn_images.append(pygame.image.load("data/graphics/buttons/close_btn_down.png").convert_alpha())
		
		self.close_btn_rect = Rect(593,7, self.close_btn_images[0].get_width(),self.close_btn_images[0].get_height());
		
		self.close_btn = SimpleButton(self.close_btn_rect, self.close_btn_images, self.screen)
		
		
		
		
		self.buttons = [self.left_arrow,self.right_arrow, self.close_btn]
		
		#* ui количества атомов
		self.atoms_ui = pygame.image.load("data/graphics/elements/atoms_ui.png").convert_alpha()
		#* позиция ui количества атомов
		self.atoms_ui_pos = (408,0)
		#* стекло ui количества атомов
		self.atoms_ui_glass = pygame.image.load("data/graphics/elements/atoms_ui_glass.png").convert_alpha()
		
		self.atoms_ui_glass_pos = []
		self.atoms_ui_glass_pos.append((521,32))
		self.atoms_ui_glass_pos.append((521,112))
		self.atoms_ui_glass_pos.append((521,192))
		self.atoms_ui_glass_pos.append((521,272))
		
		self.atom_progress = pygame.image.load("data/graphics/elements/atom_progress.png").convert()
		
		self.atim_progress_count = 20.0
		
		self.atom_progress_imgs = [];
		
		#красный
		self.atom_progress_imgs.append([self.atom_progress.subsurface(Rect(0,0,0,0)),(521,192), 0])
		
		self.atom_progress_imgs.append([self.atom_progress.subsurface(Rect(0,0,0,0)),(521,32),  0])
		
		self.atom_progress_imgs.append([self.atom_progress.subsurface(Rect(0,0,0,0)),(521,112), 0])
		
		self.atom_progress_imgs.append([self.atom_progress.subsurface(Rect(0,0,0,0)),(521,272), 0])
		
		#self.UpdateAttomIndicator(0)
		
	######################################
	# Метод UpdateAttomIndicator
	# Обновляет индикаторы заполненности собранных частей ДНК
	######################################
	def UpdateAttomIndicator(self, num_ind, new_count):
		g_ind = self.atom_progress_imgs[num_ind]
		g_ind[2] = g_ind[2] + new_count;
		int_count = g_ind[2]
		int_rast = math.ceil((int_count / self.atim_progress_count) * 86)
		if int_rast > 86:
			int_rast = self.atim_progress_count
		g_ind[0] = self.atom_progress.subsurface(Rect(0, 0, int_rast, 16))
	
	######################################
	# Метод RasterBall
	# Переводит трехмерные координаты атома в двухмерные
	# и расчитывает размер изображения атома в зависимости от перспективы
	######################################
	def RasterBall(self, ball):
		# вычисляем перспективу
		scale = self.fl / (self.fl + ball.zpos)
		# вычисляем размер изображение
		ball.scale = int(scale * self.ran_bal)
		# устанавливаем размер изображения
		ball.image_cur = pygame.transform.scale(ball.image_norm, (ball.scale,ball.scale))
		# проецируем трехмерные координаты в двухмерные
		ball.x = int(self.vpX + ball.xpos * scale)
		ball.y = int(self.vpY + ball.ypos * scale)
		# устанавливаем позицию атома
		ball.pos[self.zero] = ball.x;
		ball.pos[self.one] = ball.y;
		
	def DownToBalls(self, m_pos):
		down_balls = []
		for ball in self.bals:
			rast = (ball.scale / 2.0)
			dx = (ball.x + rast) - m_pos[0]
			dy = (ball.y + rast) - m_pos[1]
			drast = math.hypot(dx,dy)
			if drast < rast:
				down_balls.append(ball)
				#ball.image_norm = self.atom_images_over[ball.atom_num]
		
		if len(down_balls) > 0:
		
			down_balls = sorted(down_balls, key=lambda student: student.zpos, reverse=True)
			
			last_ball = down_balls[-1]
			
			if self.last_select_ball:
				if self.last_select_ball != last_ball:
					
					
					
					if self.last_select_ball.atom_num != last_ball.atom_num:
					
						index_a = self.bals.index(self.last_select_ball)
						index_b = self.bals.index(last_ball)
					
					
					
						self.StartSwapBalls(last_ball,self.last_select_ball)
						#self.bals[index_a] = last_ball
						#self.bals[index_b] = self.last_select_ball
						
						#print index_a
						#print index_b
						
					
						#self.last_select_ball.image_norm = self.atom_images_norm[self.last_select_ball.atom_num]
						#self.RasterBall(self.last_select_ball)
						self.last_select_ball = None
					else:
						print "colors equals"
						self.last_select_ball.image_norm = self.atom_images_norm[self.last_select_ball.atom_num]
						self.RasterBall(self.last_select_ball)
						self.last_select_ball = None
					
				else:
					print "click to one atom"
					self.last_select_ball.image_norm = self.atom_images_norm[self.last_select_ball.atom_num]
					self.RasterBall(self.last_select_ball)
					self.last_select_ball = None
			else:
				self.last_select_ball = last_ball
				self.last_select_ball.image_norm = self.atom_images_over[self.last_select_ball.atom_num]
				self.RasterBall(self.last_select_ball)
			
			
		elif self.last_select_ball :
			print "no click to atom"
			self.last_select_ball.image_norm = self.atom_images_norm[self.last_select_ball.atom_num]
			self.RasterBall(self.last_select_ball)
			self.last_select_ball = None
			
	
	def StartSwapBalls(self, ball_1,ball_2):
		
		self.SwapTwoBalls(ball_1,ball_2)
		
		dna_1_rem = [ball_1]
		dna_2_rem = [ball_2]
		
		win_c = 0
		win_1 = 0
		win_2 = 0
		
		atm_num_1 = -1
		atm_num_2 = -1
		
		if ball_1.num < len(ball_1.dna) and len(ball_1.dna) != 0:
			i = 1
			while ball_1.num+i <= len(ball_1.dna)-1:
				if ball_1.dna[ball_1.num+i].atom_num == ball_1.atom_num:
					dna_1_rem.append(ball_1.dna[ball_1.num+i])
					win_1 = win_1 + 1
					i = i+1
					atm_num_1 = ball_1.atom_num
				else:
					break
			
		if ball_1.num > 0 and len(ball_1.dna) != 0:
			i = 1
			while (ball_1.num - i) >= 0 and ball_1.dna[ball_1.num-i].atom_num == ball_1.atom_num:
				dna_1_rem.append(ball_1.dna[ball_1.num-i])
				win_1 = win_1 + 1
				i = i + 1
				atm_num_1 = ball_1.atom_num
				
		if ball_2.num < len(ball_2.dna) and len(ball_2.dna) != 0:
			i = 1
			while ball_2.num+i <= len(ball_2.dna)-1:
				if ball_2.dna[ball_2.num+i].atom_num == ball_2.atom_num:
					dna_2_rem.append(ball_2.dna[ball_2.num+i])
					win_2 = win_2 + 1
					i = i+1
					
					atm_num_2 = ball_2.atom_num
				else:
					break
			
		if ball_2.num > 0 and len(ball_2.dna) != 0:
			i = 1
			while (ball_2.num - i) >= 0 and ball_2.dna[ball_2.num-i].atom_num == ball_2.atom_num:
				dna_2_rem.append(ball_2.dna[ball_2.num-i])
				win_2 = win_2 + 1
				i = i + 1
				
				atm_num_2 = ball_2.atom_num
			
		#print win_1
		#print win_2
		
		if atm_num_1 > -1:
			print atm_num_1;
			self.UpdateAttomIndicator(atm_num_1, win_1)
		
		if atm_num_2 > -1:
			print atm_num_1;
			self.UpdateAttomIndicator(atm_num_2, win_2)
		
		
		if win_1 > 0:
		
			for ball in dna_1_rem:
				ball.dna.remove(ball)
				self.bals.remove(ball)
				
		if win_2 > 0:	
			for ball in dna_2_rem:
				ball.dna.remove(ball)
				self.bals.remove(ball)
			
		win_c = win_1 + win_2;	
		
		if win_c == 0:
			self.SwapTwoBalls(ball_1,ball_2)
		else:
		#	while self.dna_1
			i = 0
			for ball in self.dna_1:
				ball.num = i
				i = i+1
		
			i = 0
			for ball in self.dna_2:
				ball.num = i
				i = i+1
				
		
		
		
	
	def SwapTwoBalls(self, ball_1, ball_2):
		
		temp_atom_num = ball_1.atom_num
		
		
		ball_1.atom_num = ball_2.atom_num
		ball_2.atom_num = temp_atom_num
		
		ball_2.image_norm = self.atom_images_norm[ball_2.atom_num]
		ball_1.image_norm = self.atom_images_norm[ball_1.atom_num]
		
		self.RasterBall(ball_1)
		self.RasterBall(ball_2)
			
	def MoveAllBallLeft(self):
		for ball in self.bals:
			cosX = self.rot_cos_angle_right
			sinX = self.rot_sin_angle_left
			y1 = ball.xpos * cosX - ball.zpos * sinX;
			z1 = ball.zpos * cosX + ball.xpos * sinX;
			ball.xpos = y1;
			ball.zpos = z1;
			self.RasterBall(ball)
		self.bals = sorted(self.bals, key=lambda student: student.zpos, reverse=True)
	
	def MoveAllBallRight(self):
		for ball in self.bals:
			cosX = self.rot_cos_angle_right
			sinX = self.rot_sin_angle_right
			y1 = ball.xpos * cosX - ball.zpos * sinX;
			z1 = ball.zpos * cosX + ball.xpos * sinX;
			ball.xpos = y1;
			ball.zpos = z1;
			self.RasterBall(ball)
		self.bals = sorted(self.bals, key=lambda student: student.zpos, reverse=True)
		
	def RotateX(self, ball, angle):
		cosX = self.coss #math.cos(angle)
		sinX = self.sinn #math.sin(angle)
		y1 = ball.ypos * cosX - ball.zpos * sinX;
		z1 = ball.zpos * cosX + ball.ypos * sinX;
		ball.ypos = y1;
		ball.zpos = z1;
		
	def RotateY(self, ball, angle):
		cosX = self.coss #math.cos(angle)
		sinX = self.sinn #math.sin(angle)
		y1 = ball.xpos * cosX - ball.zpos * sinX;
		z1 = ball.zpos * cosX + ball.xpos * sinX;
		ball.xpos = y1;
		ball.zpos = z1;
		
	def Update(self):
	
		######################################
		# Этап: Обработка событий
		######################################
	
		# получаем все события и проходим по ним
		for event in pygame.event.get():
			# если это выход, то...
			if event.type == QUIT:
				# выходим
				self.ws.mainLoop = False
			# если это нажатие клавиши, то...
			elif event.type == KEYDOWN:
				if event.key == K_LEFT:
					self.MoveAllBallLeft()
				elif event.key == K_RIGHT:
					self.MoveAllBallRight()
				
			# если это нажатие кнопки мыши, то...
			elif event.type == MOUSEBUTTONDOWN:
				#
				m_pos = event.pos
				
				if self.rect_left_btn.collidepoint(m_pos):
					self.is_mouse_down = True
					self.RotationFunc = self.MoveAllBallLeft
					#self.left_arrow_img = self.left_arrow_images[2]
					self.left_arrow.Down()
				elif self.rect_right_btn.collidepoint(m_pos):
					self.is_mouse_down = True
					self.RotationFunc = self.MoveAllBallRight
					self.right_arrow.Down()
				else:
					#self.left_arrow_img = self.left_arrow_images[0]
					self.DownToBalls(m_pos)
				
				self.close_btn.TestDown(m_pos)
			# если это отпускание кнопки мыши, то...
			elif event.type == MOUSEBUTTONUP:
				m_pos = event.pos
				
				if self.close_btn.rect.collidepoint(m_pos):
					self.ws.SetCurrentScene(4)
				
				for btn in self.buttons:
					btn.Up()
				self.is_mouse_down = False
				
		# получаем позицию мыши
		self.mouse_pos = pygame.mouse.get_pos()
		
		for btn in self.buttons:
			btn.Over(self.mouse_pos)
		
		if self.is_mouse_down:
			self.RotationFunc()
		
		######################################
		# Этап: Пред прорисовка экрана
		######################################
		
		# закрашиваем экран
		self.screen.fill(self.windows_bgcolor)
		#self.screen.blit(self.bg_image,(0,0))
		# рисуем курсор
		pygame.draw.circle(self.screen, self.cur_color, self.mouse_pos, 20)
		
		######################################
		# Этап: Прорисовка элементов
		######################################

		# проходим по всему массиву атомов
		for ball in self.bals:
			# рисуем атом
			self.screen.blit(ball.image_cur,ball.pos)
			#self.screen.blit(self.num_text[ball.num],ball.pos)
			pass
		self.left_arrow.Draw()	
		
		for btn in self.buttons:
			btn.Draw()
			
		self.screen.blit(self.atoms_ui,self.atoms_ui_pos)
		
		for atms in self.atom_progress_imgs:
			self.screen.blit(atms[0],atms[1])
		
		#pygame.draw.rect(self.screen,(255,255,0), Rect(521,32,86,16))
		for inter_glasi in self.atoms_ui_glass_pos:
		
			self.screen.blit(self.atoms_ui_glass, inter_glasi)
		
		
		#self.screen.blit(self.left_arrow_img,self.rect_left_btn.topleft)
		#pygame.draw.rect(self.screen,(255,255,0), self.rect_left_btn)
		#pygame.draw.rect(self.screen,(0,255,255), self.rect_right_btn)
		
		######################################
		# Этап: Обновления экрана
		######################################
		
		pygame.display.update()
"""Celeron CPU 2.80 GHz
2.79 ГГц
504 озу
Physical Memory:		503 MB
Minimum Graphics Memory:	64 MB
Maximum Graphics Memory:	128 MB
Graphics Memory in Use:	7 MB
Processor:		x86
Processor Speed:		2793 MHZ"""